package com.example.mydianping.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.BooleanUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.example.mydianping.dto.Result;
import com.example.mydianping.mapper.ShopMapper;
import com.example.mydianping.pojo.Shop;
import com.example.mydianping.service.ShopService;
import com.example.mydianping.utils.CacheClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;

@Service
public class ShopServiceImpl implements ShopService {
    @Resource
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private ShopMapper shopMapper;
    @Autowired
    private CacheClient cacheClient;

    //使用工具类查询（解决缓存穿透版）
    @Override
    public Result getById(Long id){
        long ttl =  (long) (Math.random() * 100)+1;
//        Shop shop = cacheClient.getById("shop:cache:", id, Shop.class, a -> shopMapper.selectById(a),ttl, TimeUnit.MINUTES);
//        Shop shop = cacheClient.queryShopByLock("cache:shop:", id, Shop.class, a -> shopMapper.selectById(a), ttl, TimeUnit.MINUTES);
        Shop shop = cacheClient.queryShopByLogicExpire("cache:shop:", id, Shop.class, a -> shopMapper.selectById(a), ttl, TimeUnit.MINUTES);

        if(shop == null){
            return Result.fail("未查询到该店铺ToT");
        }
        return Result.ok(shop);
    }


//    public Result getById(Long id) {
//        //先在 redis 中查询
//        String shopJson = stringRedisTemplate.opsForValue().get("cache:shop:" + id);
//        if(StrUtil.isNotBlank(shopJson)){
//            return Result.ok(JSONUtil.toBean(shopJson,Shop.class));
//        }
//        //redis 中没有，在 mysql 中查询
//        //TODO 解决缓存穿透，若 json 为 "" 则直接响应空对象
//        if(shopJson != null){
//            return Result.fail("未查询到店铺TOT");
//        }
//        Shop shop = shopMapper.selectById(id);
//        if(shop == null){
//            //mysql 中也没有，返回未查询到
//            //TODO 解决缓存穿透，将空对象加入缓存
//            stringRedisTemplate.opsForValue().set("cache:shop:" + id,"",2, TimeUnit.MINUTES);
//            return Result.fail("未查询到该店铺ToT");
//        }
//        //查到了，将查询到的数据写入 redis
//        //随机 TTL 0~100
//        long ttl = (long)(Math.random() * 100);
//        stringRedisTemplate.opsForValue().set("cache:shop:" + id,JSONUtil.toJsonStr(shop),ttl, TimeUnit.MINUTES);
//        return Result.ok(shop);
//    }

    //尝试获取锁
    private boolean tryToGetLock(String key){
        Boolean flag = stringRedisTemplate.opsForValue().setIfAbsent(key, "aaa", 10, TimeUnit.SECONDS);
        return BooleanUtil.isTrue(flag);
    }
    //释放锁
    private void cleanLock(String key){
        stringRedisTemplate.delete(key);
    }

    @Override
    @Transactional//开启事物
    public Result update(Shop shop) {
        Long id = shop.getId();
        if(id == null){
            return Result.fail("更新店铺信息失败，未查询到该店铺");
        }
        //先更新数据库
        shopMapper.updateById(shop);
        //再删除缓存
        stringRedisTemplate.delete("cache:shop:" + id);
        return null;
    }
}
